#include "symbol_table.h"
#include <errno.h>
#include <assert.h>
#include "../alg/list.h"
#include "def.h"
#include "log.h"

symbol_table_st *symbol_table_calloc(void)
{
    symbol_table_st *symbol_table = my_calloc(1, sizeof(symbol_table_st));
    if(symbol_table == NULL)
    {
        return NULL;
    }
    return symbol_table;
}

void symbol_table_free(
    symbol_table_st * symbol_table)
{
    if(symbol_table == NULL)
    {
        return ;
    }

    if(symbol_table->next != NULL)
    {
        symbol_table_free(symbol_table->next);
    }

    symbol_table_free(symbol_table->child);
    my_free(symbol_table);
}

void root_symbol_table_free(
    root_symbol_table_st *root_symbol_table)
{
    if(root_symbol_table == NULL)
    {
        return ;
    }

    if(root_symbol_table->root != NULL)
    {
        symbol_table_free(root_symbol_table->root);
        root_symbol_table->root = NULL;
        root_symbol_table->cur = NULL;
        root_symbol_table->last_child = NULL;
    }
    my_free(root_symbol_table);
}

root_symbol_table_st *root_symbol_table_malloc(void)
{
    root_symbol_table_st *root_symbol_table 
        = my_calloc(1, sizeof(root_symbol_table_st));
    if(root_symbol_table == NULL)
    {
        ERR_FUNC_LINE("my_calloc err, %s\n", strerror(errno));
        return NULL;
    }

    root_symbol_table->root = symbol_table_calloc();
    if(root_symbol_table->root == NULL)
    {
        ERR_FUNC_LINE("symbol_table_calloc err, %s\n", strerror(errno));
        root_symbol_table_free(root_symbol_table);
    }
    root_symbol_table->cur = root_symbol_table->root;
    root_symbol_table->last_child = NULL;
    return root_symbol_table;
}

/**
 * @brief 给当前符号表添加一个子符号表
 * 
 * @param root_symbol_table 
 * @return int32_t < 0 添加失败；==0 添加成功
 */
int32_t root_symbol_table_add_child(
    root_symbol_table_st *root_symbol_table)
{
    symbol_table_st *new_table = symbol_table_calloc();
    if(new_table == NULL)
    {
        ERR_FUNC_LINE("ERR! symbol_table_calloc\n");
        return -1;
    }

    new_table->parent = root_symbol_table->cur;

    /* 有两种情况，一种是当前节点没有子节点 */
    if(root_symbol_table->cur->child == NULL)
    {
        root_symbol_table->cur->child = new_table;
        root_symbol_table->cur = new_table;
        root_symbol_table->last_child = NULL;
    }
    /* 一种是当前节点有子节点 */
    else
    {
        if(root_symbol_table->last_child == NULL)
        {
            list_insert(root_symbol_table->cur->child, new_table);
        }
        else
        {
            list_insert(root_symbol_table->last_child, new_table);
        }
        root_symbol_table->last_child = root_symbol_table->cur;
        root_symbol_table->cur = new_table;
    }

    return 0;
}

/**
 * @brief 给当前符号表添加一个兄弟符号表
 * 
 * @param root_symbol_table 
 * @return int32_t 
 */
int32_t root_symbol_table_add_brother(
    root_symbol_table_st *root_symbol_table)
{
    symbol_table_st *new_table = symbol_table_calloc();
    if(new_table == NULL)
    {
        ERR_FUNC_LINE("ERR! symbol_table_calloc\n");
        return -1;
    }
    new_table->parent = root_symbol_table->cur->parent;
    list_insert(root_symbol_table->cur, new_table);
    root_symbol_table->last_child = NULL;
    root_symbol_table->cur = new_table;
    return 0;
}

int32_t symbol_table_test(void)
{
    FUNC_BEGIN();
    root_symbol_table_st * root_symbol_table = root_symbol_table_malloc();
    assert(root_symbol_table != NULL);

    root_symbol_table_add_child(root_symbol_table);
    root_symbol_table_add_child(root_symbol_table);
    root_symbol_table_add_brother(root_symbol_table);
    root_symbol_table_add_brother(root_symbol_table);
    root_symbol_table_free(root_symbol_table);
    FUNC_FINISH();
    return 0;
}
